﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DXBase.Structs
{
	/// <summary>
	/// A plane is defined by a normal and a value, i.e. <c>Point * Normal = Value</c> if the point
	/// is on the plane.
	/// </summary>
	public struct Plane3D
	{
		public Plane3D(Vector3F p1, Vector3F p2, Vector3F p3)
		{
			Normal = (p2 - p1).Cross(p3 - p1).Normalize();
			Value = p1 * Normal;
		}
		public Plane3D(Triangle3D t)
		{
			Normal = (t.P1 - t.P0).Cross(t.P2 - t.P0).Normalize();
			Value = t.P0 * Normal;
		}
		public Plane3D(Vector3F p, Vector3F normal)
		{
			Normal = normal.Normalize();
			Value = p * Normal;
		}

		/// <summary>
		/// given <c>Vector3F p</c>, it is on a plane if <c>p * Normal = Value</c>
		/// </summary>
		public float Value;
		/// <summary>
		/// A normal to the plane
		/// </summary>
		public Vector3F Normal;

		/// <summary>
		/// A number describing the relative position of the point to the plan.
		/// Positive it's above (in the <c>Normal</c> direction), 0, it's on the plane, negative it's below.
		/// </summary>
		public float Locate(Vector3F p) { return Normal * p - Value; }

		public static Plane3D operator *(Matrix4x4F m, Plane3D p)
		{
			var n2 = m.ConvertVector(p.Normal).Normalize();
			var v2 = m.ConvertPoint(p.Value * p.Normal) * n2;

			return new Plane3D
			{
				Normal = n2,
				Value = v2,
			};
		}

		public override string ToString()
		{
			return string.Format("Plan3D({0}, -> {1})", Value, Normal);
		}
	}
}
